package cn.net.shuxing.yifu.common.service;

import cn.net.shuxing.yifu.common.bean.*;
import cn.net.shuxing.yifu.common.constant.*;
import cn.net.shuxing.yifu.common.dto.BaseDto;
import cn.net.shuxing.yifu.common.mapper.DealHistoryMapper;
import cn.net.shuxing.yifu.common.util.*;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.ScanParams;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class DealHistoryService extends HistoryService<DealHistory, DealHistoryMapper> {
    @Autowired
    private ShortService shortService;

    @Autowired
    private UserInfoBindService userInfoBindService;

    @Autowired
    private UserRealInfoService userRealInfoService;

    @Autowired
    private HangBuyService hangBuyService;

    @Autowired
    private HangSaleService hangSaleService;

    @Autowired
    private CashWalletService cashWalletService;

    @Autowired
    private MemberWalletService memberWalletService;

    @Autowired
    private UserService userService;

    @Autowired
    private JedisUtil jedisUtil;

    @Autowired
    private DealParamService dealParamService;

    @Autowired
    private FeeService feeService;

    @Autowired
    private UserCapitalService userCapitalService;

    @Autowired
    private UserDealHistoryService userDealHistoryService;

    @Autowired
    private CoinTypeService coinTypeService;

    @Autowired
    private UserRoleService userRoleService;

    public List<DealHistory> getTotalBySaleUserId(Integer saleUserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("saleUserId", saleUserId);
        paramMap.put("type", 1);
        return gets(paramMap);
    }

    public List<DealHistory> getTotalByBuyUserId(Integer buyUserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("buyUserId", buyUserId);
        paramMap.put("type", 1);
        return gets(paramMap);
    }


    public List<DealHistory> getTotalByUserId(Integer buyUserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("buyUserId", buyUserId);
        paramMap.put("type", 1);
        return gets(paramMap);
    }


    /**
     * 某个股东转账给股东的活币数量
     *
     * @param buyUserId
     * @return
     */
    public BigDecimal getShareholdeTransferToShareholdeByUserId(Integer buyUserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("saleUserId", buyUserId);
        paramMap.put("type", 1);
        List<DealHistory> gets = gets(paramMap);
        BigDecimal bigDecimal = new BigDecimal(0);
        for (DealHistory get : gets) {
            Integer type = userService.getByPrimaryKey(get.getBuyUserId()).getType();
            if (type == 2) {
                BigDecimal dealAliveCoinCount = get.getDealAliveCoinCount();
                bigDecimal = bigDecimal.add(dealAliveCoinCount);
            }
        }
        return bigDecimal;
    }


    public List<DealHistory> getTodayByBuyUserId(Integer buyUserId) {
        List<DealHistory> dealHistoryList = getByToday();
        dealHistoryList.stream().forEach(
                (x) -> {
                    if (!x.getBuyUserId().equals(buyUserId))
                        dealHistoryList.remove(x);
                }
        );
        return dealHistoryList;
    }

    public List<DealHistory> getTodayBySaleUserId(Integer saleUserId) {
        List<DealHistory> dealHistoryList = getByToday();
        dealHistoryList.stream().forEach(
                (x) -> {
                    if (!x.getSaleUserId().equals(saleUserId))
                        dealHistoryList.remove(x);
                }
        );
        return dealHistoryList;
    }

    public List<DealHistory> getsByDealIdAndDealScene(Integer dealId, Integer dealType) {
        DealHistory dealHistory = new DealHistory();
        dealHistory.clearCreateTimeAndUpdateTime();
        dealHistory.setDealScene(dealType);
        if (dealType == DealScene.HANG_BUY) {
            dealHistory.setHangBuyId(dealId);
        }
        if (dealType == DealScene.HANG_SALE) {
            dealHistory.setHangSaleId(dealId);
        }

        return mapper.select(dealHistory);
    }

    public List<DealHistory> getsByHangBuyId(Integer dealId, Integer dealType) {
        DealHistory dealHistory = new DealHistory();
        dealHistory.clearCreateTimeAndUpdateTime();
        dealHistory.setDealScene(dealType);
        dealHistory.setHangBuyId(dealId);
        return mapper.select(dealHistory);
    }

    /**
     * 系统回购
     **/
    public void systemBuyBack(Integer hangSaleId) {
        HangSale hangSale = hangSaleService.getByPrimaryKey(hangSaleId);
        Integer userId = hangSale.getUserId();
        /** 系统回购所得的总金额 **/
        BigDecimal dealAliveCount = hangSale.getSurplusCoinCount();
        BigDecimal totalAccount = dealAliveCount.multiply(hangSale.getSinglePrice());
        Integer coinTypeId = hangSale.getCoinTypeId();

        /** 获取s_ **/
//        Fee fee = feeService.getFee(userId, coinTypeId, DealScene.SYSTEM_BUY_BACK);
//        BigDecimal hangSaleBuyBack = new BigDecimal(0);
//        if (fee != null)
//            hangSaleBuyBack = fee.getFeeRatio();

        /** 计算回购服务费记录,回购手续费 **/
//        BigDecimal buyBackServiceFeeRatio = new BigDecimal(jedisUtil.get(RedisKeyCreator.buyBackServiceFeeRatio()));
        Fee sysBuyBack = feeService.getFee(userId, coinTypeId, DealScene.SYSTEM_BUY_BACK);
        Fee sysBuyBackCom = feeService.getFee(userId, coinTypeId, DealScene.SYSTEM_BUY_BACK_COMMISSION);
        BigDecimal baseDealCount = sysBuyBack.getBaseDealCount();
        BigDecimal comBaseDealCount = sysBuyBackCom.getBaseDealCount();
        BigDecimal surplusCoinCount = hangSale.getSurplusCoinCount();
        /** 插入回购服务费记录,回购手续费记录 **/
        if (surplusCoinCount.compareTo(baseDealCount) > 0) {
//            BigDecimal buyBackServiceFeeCount = hangSale.getSurplusCoinCount().multiply(sysBuyBack.getFeeRatio());
            BigDecimal buyBackServiceFeeCount = (hangSale.getSurplusCoinCount().subtract(baseDealCount)).multiply(sysBuyBack.getFeeRatio());
            userDealHistoryService.insert(userId, coinTypeId, DealType.FEE, DealScene.SYSTEM_BUY_BACK, buyBackServiceFeeCount, hangSale.getSinglePrice(), UserType.MEMBER, hangSale.getOrderKey());
        }

        if (surplusCoinCount.compareTo(comBaseDealCount) > 0) {
            BigDecimal buyBackCommission = (hangSale.getSurplusCoinCount().subtract(comBaseDealCount)).multiply(sysBuyBackCom.getFeeRatio());
            userDealHistoryService.insert(userId, coinTypeId, DealType.FEE, DealScene.SYSTEM_BUY_BACK_COMMISSION, buyBackCommission, hangSale.getSinglePrice(), UserType.MEMBER, hangSale.getOrderKey());
        }


        /** 扣除回购服务费,回购手续费 **/
        feeService.reduceFee(userId, coinTypeId, DealScene.SYSTEM_BUY_BACK, hangSale.getSurplusCoinCount(), hangSale.getSinglePrice(), UserType.MEMBER);
        feeService.reduceFee(userId, coinTypeId, DealScene.SYSTEM_BUY_BACK_COMMISSION, hangSale.getSurplusCoinCount(), hangSale.getSinglePrice(), UserType.MEMBER);

        /** 增加现金 **/
        cashWalletService.addCash(userId, totalAccount, DealType.SYS_BUY_BACK, hangSale.getOrderKey());
        /** 减少虚拟币 **/
        userCapitalService.reduceAliveCoin(userId, coinTypeId, hangSale.getAliveCoinCount(), UserType.MEMBER);
//        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeId(userId, coinTypeId);
//        BigDecimal userCapitalAliveCoinCount = userCapital.getAliveCoinCount();
//        userCapital.setAliveCoinCount(userCapitalAliveCoinCount.subtract(buyBackServiceFeeCount));
//        userCapitalService.update(userCapital);
        hangSaleService.setHangSaleCompleted(hangSale);
        /** 添加到交易历史表中 **/
        Integer saleUserId = userId;
        Integer buyUserId = 0;

        insert(buyUserId, saleUserId, null, hangSaleId, DealScene.SYSTEM_BUY_BACK, coinTypeId, hangSale.getSinglePrice(), dealAliveCount, DealState.COMPLETED);
        userDealHistoryService.insert(userId, coinTypeId, DealType.SYS_BUY_BACK, DealScene.NONE, dealAliveCount, hangSale.getSinglePrice(), UserType.MEMBER, hangSale.getOrderKey());
        //userDealHistoryService.insert(userId,coinTypeId,DealType.HANG_SALE,DealScene.SYSTEM_BUY_BACK,dealAliveCount,hangSale.getSinglePrice());
        /** 记录总交易数 **/
        userCapitalService.addDealCount(userId, coinTypeId, dealAliveCount);
        jedisUtil.del(RedisKeyCreator.ablePublishHangBuy(userId));
    }

    public void insert(Integer buyUserId, Integer saleUserId, Integer hangBuyId, Integer hangSaleId,
                       Integer dealScene, Integer coinTypeId,
                       BigDecimal singlePrice, BigDecimal dealAliveCount) {
        DealHistory dealHistory = new DealHistory();
        dealHistory.setBuyUserId(buyUserId);
        dealHistory.setSaleUserId(saleUserId);
        dealHistory.setHangBuyId(hangBuyId);
        dealHistory.setHangSaleId(hangSaleId);
        dealHistory.setDealScene(dealScene);
        dealHistory.setCoinTypeId(coinTypeId);
        dealHistory.setSinglePrice(singlePrice);
        dealHistory.setDealAliveCoinCount(dealAliveCount);
        dealHistory.setDealAliveCoinCount(dealAliveCount);
        dealHistory.setState(DealState.COMPLETED);
        insert(dealHistory);

    }

    public DealHistory insert(Integer buyUserId, Integer saleUserId, Integer hangBuyId, Integer hangSaleId,
                              Integer dealScene, Integer coinTypeId,
                              BigDecimal singlePrice, BigDecimal dealAliveCount, Integer state) {
        DealHistory dealHistory = new DealHistory();
        dealHistory.setBuyUserId(buyUserId);
        dealHistory.setSaleUserId(saleUserId);
        dealHistory.setHangBuyId(hangBuyId);
        dealHistory.setHangSaleId(hangSaleId);
        dealHistory.setDealScene(dealScene);
        dealHistory.setCoinTypeId(coinTypeId);
        dealHistory.setSinglePrice(singlePrice);
        dealHistory.setDealAliveCoinCount(dealAliveCount);
        dealHistory.setState(state);
        insert(dealHistory);
        return getByPrimaryKey(dealHistory.getId());
    }

    @Override
    public DealHistory get(DealHistory bean) {
        bean.setState(DealState.COMPLETED);
        return super.get(bean);
    }

    @Override
    public List<DealHistory> gets(DealHistory bean) {
        bean.setState(DealState.COMPLETED);
        return super.gets(bean);
    }

    /**
     * 对匹配的挂卖单和挂买单进行自动交易
     **/

    public void deal(Integer hangBuyId, Integer hangSaleId) {
        HangBuy hangBuy = hangBuyService.getByPrimaryKey(hangBuyId);
        HangSale hangSale = hangSaleService.getByPrimaryKey(hangSaleId);
        Integer coinTypeId = hangBuy.getCoinTypeId();

        Integer hangBuyUserId = hangBuy.getUserId();
        Integer hangSaleUserId = hangSale.getUserId();

        BigDecimal hangBuySurplusCoinCount = hangBuy.getSurplusCoinCount();
        BigDecimal hangSaleSurplusCoinCount = hangSale.getSurplusCoinCount();

        int compareResult = hangBuySurplusCoinCount.compareTo(hangSaleSurplusCoinCount);
        /** 4. 判断挂买后数量是否会超过交易钱包最大持有量 **/
        BigDecimal maxCount = new BigDecimal(jedisUtil.get(RedisKeyCreator.memberKeepAliveCoinMaxCount()));
        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(hangBuyUserId, coinTypeId, UserType.MEMBER);
        BigDecimal nowAliveCoinCout = userCapital.getAliveCoinCount();
        BigDecimal allowCount = maxCount.subtract(nowAliveCoinCout);
        BigDecimal singlePrice = hangBuy.getSinglePrice();
        BigDecimal dealCount = hangSale.getSurplusCoinCount();
        boolean checkMaxCout = true;
        if (dealCount.compareTo(allowCount) > 0) {
            dealCount = allowCount;
            checkMaxCout = false;
        }
        if (compareResult > 0) {
            /**
             * 买方买入卖方的活币，给卖方现金
             * 如果买方要的活币大于卖方，则卖方将全部活币卖给买方
             * 设置挂卖单为已完成
             */
            //挂卖单的剩余数量多余与会员可买数量 交易数量为可买数量

            memberWalletService.addAliveCoin(hangBuyUserId, coinTypeId, dealCount);
            memberWalletService.addCash(hangSaleUserId, dealCount.multiply(singlePrice), CashChangeType.CASH_HANG_SALE, hangSale.getOrderKey());
            hangBuyService.reduceSurplusCoinCount(hangBuyId, dealCount);
            if (checkMaxCout) {
                hangSaleService.setHangSaleCompleted(hangSale);
            } else {
                hangSaleService.reduceSurplusCoinCount(hangSaleId, dealCount);
            }

            /** 将交易记录存入表中 **/
            insert(hangBuyUserId, hangSaleUserId, hangBuyId, hangSaleId, DealType.HANG_BUY, coinTypeId, singlePrice, dealCount);
            insert(hangBuyUserId, hangSaleUserId, hangBuyId, hangSaleId, DealType.HANG_SALE, coinTypeId, singlePrice, dealCount);
            userDealHistoryService.insert(hangBuyUserId, coinTypeId, DealType.HANG_BUY, DealScene.NONE, dealCount, singlePrice, UserType.MEMBER, hangBuy.getOrderKey());
            userDealHistoryService.insert(hangSaleUserId, coinTypeId, DealType.HANG_SALE, DealScene.NONE, dealCount, singlePrice, UserType.MEMBER, hangSale.getOrderKey());
            /** 记录总交易量 **/
            userCapitalService.addDealCount(hangBuyUserId, coinTypeId, dealCount);
            userCapitalService.addDealCount(hangSaleUserId, coinTypeId, dealCount);

        } else if (compareResult == 0) {
            /**
             * 买方买入卖方的活币，给卖方现金
             * 如果买方要的活币等于卖方，则卖方将剩余活币卖给买方
             * 设置挂买单和挂卖单为已完成
             */
            memberWalletService.addAliveCoin(hangBuyUserId, coinTypeId, dealCount);
            memberWalletService.addCash(hangSaleUserId, dealCount.multiply(singlePrice), CashChangeType.CASH_HANG_SALE, hangSale.getOrderKey());
            if (checkMaxCout) {
                hangBuyService.setHangBuyCompleted(hangBuy);
                hangSaleService.setHangSaleCompleted(hangSale);
            } else {
                hangSaleService.reduceSurplusCoinCount(hangSaleId, dealCount);
                hangBuyService.reduceSurplusCoinCount(hangBuyId, dealCount);
            }

            /** 将交易记录存入表中 **/
            insert(hangBuyUserId, hangSaleUserId, hangBuyId, hangSaleId, DealScene.HANG_BUY, coinTypeId, singlePrice, dealCount);
            insert(hangBuyUserId, hangSaleUserId, hangBuyId, hangSaleId, DealScene.HANG_SALE, coinTypeId, singlePrice, dealCount);

            /** 存入用户交易表 **/
            userDealHistoryService.insert(hangBuyUserId, coinTypeId, DealType.HANG_BUY, DealScene.NONE, dealCount, singlePrice, UserType.MEMBER, hangBuy.getOrderKey());
            userDealHistoryService.insert(hangSaleUserId, coinTypeId, DealType.HANG_SALE, DealScene.HANG_SALE, dealCount, singlePrice, UserType.MEMBER, hangSale.getOrderKey());

            /** 记录总交易量 **/
            userCapitalService.addDealCount(hangBuyUserId, coinTypeId, dealCount);
            userCapitalService.addDealCount(hangSaleUserId, coinTypeId, dealCount);
        } else if (compareResult < 0) {
            /**
             * 买方买入卖方的活币，给卖方现金
             * 如果买方要的活币小于卖方，买方买入自己还需要的所有活币
             * 设置挂买单为已完成
             */

            dealCount = hangBuy.getSurplusCoinCount();
            if (dealCount.compareTo(allowCount) > 0) {
                dealCount = allowCount;
                checkMaxCout = false;
            }
            memberWalletService.addAliveCoin(hangBuyUserId, coinTypeId, dealCount);
            memberWalletService.addCash(hangSaleUserId, dealCount.multiply(singlePrice), CashChangeType.CASH_HANG_SALE, hangSale.getOrderKey());
            hangSaleService.reduceSurplusCoinCount(hangSaleId, dealCount);
            if (checkMaxCout) {
                hangBuyService.setHangBuyCompleted(hangBuy);
            } else {
                hangBuyService.reduceSurplusCoinCount(hangBuyId, dealCount);
            }

            /** 将交易记录存入表中 **/
            userDealHistoryService.insert(hangBuyUserId, coinTypeId, DealType.HANG_BUY, DealScene.HANG_BUY, dealCount, singlePrice, UserType.MEMBER, hangBuy.getOrderKey());
            userDealHistoryService.insert(hangSaleUserId, coinTypeId, DealType.HANG_SALE, DealScene.HANG_SALE, dealCount, singlePrice, UserType.MEMBER, hangSale.getOrderKey());
            /** 记录总交易量 **/
            userCapitalService.addDealCount(hangBuyUserId, coinTypeId, dealCount);
            userCapitalService.addDealCount(hangSaleUserId, coinTypeId, dealCount);
        }
    }

    public List<DealHistory> getsByDayCount(int shareholderId, int count) {
        TimeExample example = new TimeExample(getBeanClass());
        example.dayGreaterThan("createDate", count);
        return mapper.selectByExample(example);
    }


    /**
     * 手动购买挂卖单
     *
     * @param buyUserId
     * @param hangSaleId
     * @param count
     * @return
     */
    public BaseDto buyHangSale(Integer buyUserId, Integer hangSaleId, BigDecimal count) {
        boolean b = userService.hasRole(buyUserId, UserType.MEMBER);
        if (!b)
            return BaseDto.error("你不是已激活会员,不能购买活币");
        Integer state = userService.getByPrimaryKeyWithoutComplete(buyUserId).getState();
        if (state != UserState.OK)
            return BaseDto.error("当前状态无法进行交易");

        HangSale hangSale = hangSaleService.getByPrimaryKey(hangSaleId);

        /** 如果要买的数量大于挂卖单余额,报错 **/
        if (hangSale.getSurplusCoinCount().compareTo(count) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("该比挂卖单余额不足");
            return baseDto;
        }

        /** 如果 要买的数量 + 用户活币余额 - 手续费 >  交易钱包活币最高持有量, 报错**/
        Integer coinTypeId = hangSale.getCoinTypeId();
        Fee fee = feeService.getFee(buyUserId, coinTypeId, DealScene.HANG_BUY);
        BigDecimal feeRatio = fee.getFeeRatio();
        BigDecimal baseDealCount = fee.getBaseDealCount();
        BigDecimal feeCount = (count.subtract(baseDealCount)).multiply(feeRatio);
        UserCapital buyUserCapital = userCapitalService.getByUserIdAndCoinTypeId(buyUserId, coinTypeId);
        BigDecimal buyUserAliveCoinCount = buyUserCapital.getAliveCoinCount();
        BigDecimal dealWalletMaxCount = new BigDecimal(dealParamService.getValue(buyUserId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MAX_COUNT));
        BigDecimal dealWalletMinCount = new BigDecimal(dealParamService.getValue(buyUserId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MIN_COUNT));

        if (feeCount.compareTo(buyUserAliveCoinCount.subtract(dealWalletMinCount)) > 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("钱包可用余额不足以支付手续费,请先购买虚拟币");
            return baseDto;
        }

        if (count.add(buyUserAliveCoinCount).subtract(feeCount).compareTo(dealWalletMaxCount) > 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("要买的数量超过了限制,交易钱包活币最高持有量为: " + dealWalletMaxCount);
            return baseDto;
        }

        /** 如果买方现金钱包不够支付,报错 **/
        BigDecimal cashCount = cashWalletService.getByPrimaryKey(buyUserId).getCashCount();
        BigDecimal shouldPayCashCount = count.multiply(hangSale.getSinglePrice());
        if (cashCount.compareTo(shouldPayCashCount) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("现金余额不足");
            return baseDto;
        }

        /** 开始交易 **/

        /** 2.买方减少现金 **/
        memberWalletService.reduceCash(buyUserId, shouldPayCashCount, CashChangeType.CASH_HANG_BUY, hangSale.getOrderKey());
        /** 插入手续费记录**/

        userDealHistoryService.insert(buyUserId, coinTypeId, DealType.FEE, DealScene.HANG_SALE, feeCount, hangSale.getSinglePrice(), UserType.MEMBER, hangSale.getOrderKey());
//        userDealHistoryService.insert(buyUserId,coinTypeId,DealType.HANG_BUY,DealScene.HANG_BUY,count,hangSale.getSinglePrice(),UserType.MEMBER);
        /** 1.扣除手续费**/
        feeService.reduceFee(buyUserId, coinTypeId, DealScene.HANG_BUY, count, hangSale.getSinglePrice(), UserType.MEMBER);
        Integer saleUserId = hangSale.getUserId();
        BigDecimal singlePrice = hangSale.getSinglePrice();
        /** 交易记录存入表中 **/
        DealHistory dealHistory = insert(buyUserId, saleUserId, null, hangSaleId, DealType.HANG_SALE, coinTypeId, singlePrice, count, DealState.DEALING);
        insert(buyUserId, saleUserId, null, hangSaleId, DealScene.HANG_BUY, coinTypeId, singlePrice, count, DealState.DEALING);
        /**5挂卖单减少对应数量**/
        BigDecimal surplusCoinCount = hangSale.getSurplusCoinCount();
        surplusCoinCount = surplusCoinCount.subtract(count);
        hangSale.setSurplusCoinCount(surplusCoinCount);
        hangSaleService.update(hangSale);
        /**4手动方虚拟币**/
        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(buyUserId, coinTypeId, UserType.MEMBER);
        BigDecimal oldAliveCoinCount = userCapital.getAliveCoinCount();
        BigDecimal newAliveCoinCount = oldAliveCoinCount.add(count);
        userCapital.setAliveCoinCount(newAliveCoinCount);
        userCapitalService.update(userCapital);
        userDealHistoryService.insert(buyUserId, coinTypeId, DealType.HANG_BUY, DealScene.NONE, count, hangSale.getSinglePrice(), UserType.MEMBER, hangSale.getOrderKey());
        /**3增加卖方现金**/
        CashWallet hangSaleCashWallet = cashWalletService.getByUserId(hangSale.getUserId());
        BigDecimal oldCashCount = hangSaleCashWallet.getCashCount();
        BigDecimal newCashCount = oldCashCount.add(count.multiply(singlePrice));
        hangSaleCashWallet.setCashCount(newCashCount);
        cashWalletService.update(hangSaleCashWallet);
        memberWalletService.addCash(hangSale.getUserId(), count.multiply(singlePrice), CashChangeType.CASH_HANG_SALE, hangSale.getOrderKey());
        //Jedis //jedis = jedisUtil.getJedis();
        jedisUtil.sadd(RedisKeyCreator.manualBuyHangSaleQueue(), JSON.toJSONString(dealHistory));
        //jedisUtil.close();
        BaseDto baseDto = new BaseDto();
        baseDto.setData(dealHistory);
        return baseDto;
    }

    /**
     * 执行手动买入挂卖
     **/
    public void doBuyHangSale() {
        //Jedis //jedis = jedisUtil.getJedis();
        List<String> dealHistoryListStr = jedisUtil.sscan(RedisKeyCreator.manualBuyHangSaleQueue(), "0", new ScanParams().match("*")).getResult();
        if (dealHistoryListStr == null || dealHistoryListStr.isEmpty()) {
            //jedisUtil.close();
            return;
        }
        for (String dealHistoryStr : dealHistoryListStr) {
            System.out.println(dealHistoryStr);
            DealHistory dealHistory = JSON.parseObject(dealHistoryStr, DealHistory.class);
            Integer buyUserId = dealHistory.getBuyUserId();
            Integer coinTypeId = dealHistory.getCoinTypeId();
            BigDecimal count = dealHistory.getDealAliveCoinCount();
            Integer saleUserId = dealHistory.getSaleUserId();
            Integer hangSaleId = dealHistory.getHangSaleId();
            BigDecimal singlePrice = dealHistory.getSinglePrice();
            BigDecimal shouldPayCashCount = count.multiply(singlePrice);

            /** 买方增加活币 **/
            memberWalletService.addAliveCoin(buyUserId, coinTypeId, count);

            /** 卖方增加现金, 挂卖单余额减少活币 **/
            memberWalletService.addCash(saleUserId, shouldPayCashCount, CashChangeType.CASH_HANG_BUY, hangSaleService.getByPrimaryKey(hangSaleId).getOrderKey());
            HangSale hangSale = hangSaleService.getByPrimaryKey(hangSaleId);

            if (hangSale.getState() != DealState.DEALING) {
                /** 修改表 **/
                dealHistory.setState(DealState.FAIL);
                update(dealHistory);
                jedisUtil.srem(RedisKeyCreator.manualBuyHangSaleQueue(), dealHistoryStr);
            }

            BigDecimal surplusCoinCount = hangSale.getSurplusCoinCount();
            surplusCoinCount = surplusCoinCount.subtract(count);
            hangSale.setSurplusCoinCount(surplusCoinCount);
            hangSaleService.update(hangSale);
            if (hangSale.getSurplusCoinCount().compareTo(new BigDecimal(0)) == 0) {
                hangSaleService.setHangSaleCompleted(hangSale);
            }

            /** 收手续费 **/
//            feeService.reduceFee(buyUserId, coinTypeId, DealScene.HANG_BUY, count, singlePrice, UserType.MEMBER);
            feeService.reduceFee(buyUserId, coinTypeId, DealScene.HANG_BUY, count, singlePrice, UserType.MEMBER);

            /** 修改表 **/
            dealHistory.setState(DealState.COMPLETED);
            update(dealHistory);

            userDealHistoryService.insert(buyUserId, coinTypeId, DealType.HANG_BUY, DealScene.NONE, count, singlePrice, UserType.MEMBER, hangSale.getOrderKey());
            userDealHistoryService.insert(saleUserId, coinTypeId, DealType.HANG_SALE, DealScene.NONE, count, singlePrice, UserType.MEMBER, hangSale.getOrderKey());


            jedisUtil.srem(RedisKeyCreator.manualBuyHangSaleQueue(), dealHistoryStr);
            /** 记录总交易量 **/
            userCapitalService.addDealCount(buyUserId, coinTypeId, count);
            userCapitalService.addDealCount(saleUserId, coinTypeId, count);
        }
        //jedisUtil.close();
    }

    /**
     * 执行手动卖出挂买
     **/
    public void doSaleHangBuy() {
        //Jedis //jedis = jedisUtil.getJedis();
        List<String> dealHistoryListStr = jedisUtil.sscan(RedisKeyCreator.manualSaleHangBuyQueue(), "0", new ScanParams().match("*")).getResult();
        if (dealHistoryListStr == null || dealHistoryListStr.isEmpty()) {
            //jedisUtil.close();
            return;
        }

        for (String dealHistoryStr : dealHistoryListStr) {
            System.out.println(dealHistoryStr);
            DealHistory dealHistory = JSON.parseObject(dealHistoryStr, DealHistory.class);

            Integer buyUserId = dealHistory.getBuyUserId();
            Integer coinTypeId = dealHistory.getCoinTypeId();
            BigDecimal count = dealHistory.getDealAliveCoinCount();
            Integer saleUserId = dealHistory.getSaleUserId();
            Integer hangBuyId = dealHistory.getHangBuyId();
            Integer hangSaleId = dealHistory.getHangSaleId();
            BigDecimal singlePrice = dealHistory.getSinglePrice();
            BigDecimal shouldPayCashCount = count.multiply(singlePrice);

            HangBuy hangBuy = hangBuyService.getByPrimaryKey(hangBuyId);
            HangSale hangSale = hangSaleService.getByPrimaryKey(hangSaleId);
            if (hangBuy == null)
                continue;
            if (hangBuy.getState() != DealState.DEALING) {
                dealHistory.setState(DealState.FAIL);
                update(dealHistory);
                jedisUtil.srem(RedisKeyCreator.manualBuyHangSaleQueue(), dealHistoryStr);
                continue;
            }


            /** 买方增加活币,减少现金 **/
            memberWalletService.addAliveCoin(buyUserId, coinTypeId, count);
            memberWalletService.reduceCash(buyUserId, singlePrice.multiply(count), CashChangeType.CASH_HANG_SALE, hangBuy.getOrderKey());

            /** 卖方增加现金,减少活币, 挂买单余额减少活币 **/
            memberWalletService.addCash(saleUserId, shouldPayCashCount, CashChangeType.CASH_HANG_SALE, hangBuy.getOrderKey());

            BigDecimal surplusCoinCount = hangBuy.getSurplusCoinCount();
            surplusCoinCount = surplusCoinCount.subtract(count);
            hangBuy.setSurplusCoinCount(surplusCoinCount);
            if (hangBuy.getSurplusCoinCount().compareTo(new BigDecimal(0)) == 0) {
                hangBuyService.setHangBuyCompleted(hangBuy);
            }
            hangBuyService.update(hangBuy);
            /** 收手续费 **/
//            feeService.reduceFee(buyUserId, coinTypeId, DealScene.HANG_BUY, count, singlePrice, UserType.MEMBER);
//            feeService.reduceFee(saleUserId, coinTypeId, DealScene.HANG_SALE, count, singlePrice, UserType.MEMBER);
            /** 交易记录存入表中 **/
            dealHistory.setState(DealState.COMPLETED);
            update(dealHistory);
            userDealHistoryService.insert(buyUserId, coinTypeId, DealType.HANG_BUY, DealScene.NONE, count, singlePrice, UserType.MEMBER, hangBuy.getOrderKey());
            userDealHistoryService.insert(saleUserId, coinTypeId, DealType.HANG_SALE, DealScene.NONE, count, singlePrice, UserType.MEMBER, hangSale.getOrderKey());
            jedisUtil.srem(RedisKeyCreator.manualSaleHangBuyQueue(), dealHistoryStr);

            /** 记录总交易量 **/
            userCapitalService.addDealCount(buyUserId, coinTypeId, count);
            userCapitalService.addDealCount(saleUserId, coinTypeId, count);
        }
        //jedisUtil.close();
    }

    /**
     * 手动卖给挂买单
     *
     * @param saleUserId
     * @param hangBuyId
     * @param count
     * @return
     */
    public BaseDto saleHangBuy(Integer saleUserId, Integer hangBuyId, BigDecimal count) {
        boolean b = userService.hasRole(saleUserId, UserType.MEMBER);
        if (!b)
            return BaseDto.error("你不是会员,不能卖出活币");
//        Integer state = userService.getByPrimaryKeyWithoutComplete(saleUserId).getState();
        Integer state = userRoleService.getUserStateByUserIdAndUserType(saleUserId, UserType.MEMBER);
        if (state != UserState.OK)
            return BaseDto.error("当前状态无法进行交易");

        HangBuy hangBuy = hangBuyService.getByPrimaryKey(hangBuyId);

        /** 如果要买的数量大于挂卖单余额,报错 **/
        if (hangBuy.getSurplusCoinCount().compareTo(count) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("该笔挂买单余额不足");
            return baseDto;
        }

        Integer coinTypeId = hangBuy.getCoinTypeId();

//        BigDecimal buyUserAliveCoinCount = userCapitalService.getByUserIdAndCoinTypeId(buyUserId, coinTypeId).getAliveCoinCount();
//        BigDecimal dealWalletMaxCount = new BigDecimal(dealParamService.getValue(buyUserId, coinTypeId, UserParamConst.DEAL_WALLET_MAX_COUNT));
//        if (count.add(buyUserAliveCoinCount).compareTo(dealWalletMaxCount) > 0)
//        {
//            BaseDto baseDto = new BaseDto();
//            baseDto.setCode(CodeConst.ERROR);
//            baseDto.setMsg("要买的数量超过了限制,交易钱包活币最高持有量为: " + dealWalletMaxCount);
//            return baseDto;
//        }
        BigDecimal userShortCount = new BigDecimal(shortService.getUserShortCount(saleUserId, coinTypeId));
        BigDecimal shortCount = new BigDecimal(dealParamService.getValue(saleUserId, coinTypeId, UserParamConst.SHORT_COUNT));
        /** 如果卖方交易钱包余额不够支付,报错 **/
        BigDecimal aliveCoinCount = userCapitalService.getByUserIdAndCoinTypeId(saleUserId, coinTypeId).getAliveCoinCount();
        BigDecimal shouldPayCashCount = count;
        if (userShortCount.compareTo(shortCount) < 0) {
            if (aliveCoinCount.compareTo(shouldPayCashCount) < 0) {
                BaseDto baseDto = new BaseDto();
                baseDto.setCode(CodeConst.ERROR);
                baseDto.setMsg("卖方活币余额不足");
                return baseDto;
            }
        } else {
            BigDecimal mincount = new BigDecimal(jedisUtil.get(RedisKeyCreator.memberKeepAliveCoinMinCount()));
            aliveCoinCount = aliveCoinCount.subtract(mincount);
            if (aliveCoinCount.compareTo(shouldPayCashCount) < 0) {
                BaseDto baseDto = new BaseDto();
                baseDto.setCode(CodeConst.ERROR);
                baseDto.setMsg("卖方活币余额不足");
                return baseDto;
            }
        }

        /** 开始交易 **/
        /**2卖方减少虚拟币**/
        memberWalletService.reduceAliveCoin(saleUserId, coinTypeId, count);
        Integer buyUserId = hangBuy.getUserId();
        BigDecimal singlePrice = hangBuy.getSinglePrice();

        /** 1.1插入手续费记录**/
        Fee fee = feeService.getFee(saleUserId, coinTypeId, DealScene.HANG_SALE);
        BigDecimal feeRatio = fee.getFeeRatio();
        BigDecimal baseDealCount = fee.getBaseDealCount();
        BigDecimal feeCount = (count.subtract(baseDealCount)).multiply(feeRatio);

        userDealHistoryService.insert(saleUserId, coinTypeId, DealType.FEE, DealScene.HANG_SALE, feeCount, hangBuy.getSinglePrice(), UserType.MEMBER, hangBuy.getOrderKey());
        /** 1.扣除手续费**/
        feeService.reduceFee(saleUserId, coinTypeId, DealScene.HANG_SALE, count, hangBuy.getSinglePrice(), UserType.MEMBER);
        /** 5.挂买单减少对应数量*/
        BigDecimal oldSurplusCoinCount = hangBuy.getSurplusCoinCount();
        BigDecimal newSurplusCoinCount = oldSurplusCoinCount.subtract(count);
        hangBuy.setSurplusCoinCount(newSurplusCoinCount);
        hangBuyService.update(hangBuy);
        /** 4.挂买方增加虚拟币**/
        UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(hangBuy.getUserId(), coinTypeId, UserType.MEMBER);
        BigDecimal oldAliveCoinCount = userCapital.getAliveCoinCount();
        BigDecimal newAliveCoinCount = oldAliveCoinCount.add(count);
        userCapital.setAliveCoinCount(newAliveCoinCount);
        userCapitalService.update(userCapital);
        /** 3手动方增加现金**/
//        CashWallet cashWallet = cashWalletService.getByUserId(saleUserId);
//        BigDecimal oldCashCount = cashWallet.getCashCount();
//        BigDecimal newCashCount = oldCashCount.add();
//        cashWallet.setCashCount(newCashCount);
//        cashWalletService.update(cashWallet);
        memberWalletService.addCash(saleUserId, count.multiply(singlePrice), CashChangeType.CASH_HANG_SALE, hangBuy.getOrderKey());
        /** 交易记录存入表中 **/
        DealHistory dealHistory = insert(buyUserId, saleUserId, hangBuyId, null, DealType.HANG_SALE, coinTypeId, singlePrice, count, DealState.DEALING);
        insert(buyUserId, saleUserId, hangBuyId, null, DealType.HANG_BUY, coinTypeId, singlePrice, count, DealState.DEALING);
        userDealHistoryService.insert(saleUserId, coinTypeId, DealType.HANG_SALE, DealScene.NONE, count, singlePrice, UserType.MEMBER, hangBuy.getOrderKey());
        //Jedis //jedis = jedisUtil.getJedis();
        jedisUtil.sadd(RedisKeyCreator.manualSaleHangBuyQueue(), JSON.toJSONString(dealHistory));
        //jedisUtil.close();

        BaseDto baseDto = new BaseDto();
        baseDto.setData(dealHistory);
        return baseDto;
    }

    @Override
    protected void complete(DealHistory bean) {
        if (bean == null)
            return;
        Integer buyUserId = bean.getBuyUserId();
        UserRealInfo userRealInfo = userRealInfoService.getByPrimaryKey(buyUserId);

        String realName = "";
        if (userRealInfo != null)
            realName = userRealInfo.getRealName();
        bean.setBuyUserName(realName);
        UserInfoBind buyInfoBind = userInfoBindService.getByPrimaryKey(buyUserId);

        String buyPhoneNum = "";
        if (buyInfoBind != null)
            buyPhoneNum = buyInfoBind.getPhoneNum();
        bean.setBuyPhoneNum(buyPhoneNum);
        Integer saleUserId = bean.getSaleUserId();

        String saleUserName = "";
        userRealInfo = userRealInfoService.getByPrimaryKey(saleUserId);
        if (userRealInfo != null)
            saleUserName = userRealInfo.getRealName();
        bean.setSaleUserName(saleUserName);

        UserInfoBind saleInfoBind = userInfoBindService.getByPrimaryKey(saleUserId);
        String salePhoneNum = "";
        if (saleInfoBind != null)
            salePhoneNum = saleInfoBind.getPhoneNum();
        bean.setSalePhoneNum(salePhoneNum);

        CoinType coinType = coinTypeService.getByPrimaryKey(bean.getCoinTypeId());
        if (coinType != null)
            bean.setSimpleName(coinType.getSimpleName());

    }

    public List<DealHistory> getAllNewest() {
        CommonExample example = new CommonExample(DealHistory.class);
        example.setOrderByClause("create_time ASC");
        example.equals("state", DealState.COMPLETED);
        List<DealHistory> dealHistoryList = mapper.selectByExample(example);
        completeAll(dealHistoryList);
        return dealHistoryList;
    }

    public List<DealHistory> getAllNewestWithoutComplete(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<DealHistory> dealHistoryList = ((DealHistoryMapper) mapper).getAllNewestWithoutComplete();
        for (DealHistory dealHistory : dealHistoryList) {
            Integer coinTypeId = dealHistory.getCoinTypeId();
            dealHistory.setSimpleName(coinTypeService.getByPrimaryKey(coinTypeId).getSimpleName());
            if (dealHistory.getHangBuyId() != 0 && dealHistory.getHangSaleId() != 0) {
                dealHistory.setType("自动");
            } else {
                dealHistory.setType("手动");
            }
            dealHistory.setSimpleName(coinTypeService.getByPrimaryKey(coinTypeId).getSimpleName());
        }
        return dealHistoryList;
    }

    public List<DealHistory> getMineNewest(Integer userId) {
        Example example = new Example(DealHistory.class);
        Example.Criteria criteria2 = example.createCriteria();
        criteria2.andEqualTo("deleted", 0);
        example.and(criteria2);
        Example.Criteria criteria = example.createCriteria();
        criteria.orEqualTo("buyUserId", userId);
        criteria.orEqualTo("saleUserId", userId);
        example.and(criteria);
        example.setOrderByClause("create_time ASC");
        Example.Criteria criteria1 = example.createCriteria();
        criteria1.andEqualTo("state", DealState.COMPLETED);
        example.and(criteria);
        List<DealHistory> dealHistoryList = mapper.selectByExample(example);
        completeAll(dealHistoryList);
        return dealHistoryList;
    }

}
